package com.example.springboot_study.common.deployment;

import org.activiti.engine.*;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author : liqun
 * @createTime : 2021/10/21 14:38
 */
@Component
public class ActivityService {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private ProcessEngine processEngine;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private HistoryService historyService;

    /**
     * 部署一个简单的流程示例
     */
    //@Override
    public void deployAProcess() {
        repositoryService.createDeployment()
                .addClasspathResource("process/holiday.bpmn")
                .addClasspathResource("process/holiday.png")
                .name("请假流程")
                .deploy();
    }

    /**
     * 查看流程部署
     */
    //@Override
    public void queryProcessDeployment() {
        DeploymentQuery query = repositoryService.createDeploymentQuery();
        List<Deployment> list = query.deploymentName("请假流程").list();
        System.out.println(list);

        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> list1 = processDefinitionQuery.deploymentId(list.get(0).getId()).list();
        System.out.println(list1);
    }


    /**
     * 启动流程实例:
     *      前提是先已经完成流程定义的部署工作
     *
     *      背后影响的表：
     *      act_hi_actinst          已完成的活动信息
     *      act_hi_identitylink     参与者信息
     *      act_hi_procinst         流程实例
     *      act_hi_taskinst         任务实例
     *      act_ru_execution        执行表
     *      act_ru_identitylink     参与者信息
     *      act_ru_task             任务表
     */
   // @Override
    public void startPorcInstance(){
        //创建流程实例,通过流程定义的id
        //通过流程部署的key启动
//        runtimeService.startProcessInstanceByKey("myProcess_1");
        //通过流程部署id启动
        runtimeService.startProcessInstanceById("holiday:1:47504");

    }

    /**
     * 查看用户当前任务
     */
    //@Override
    public void queryUserTask() {
        TaskQuery taskQuery = taskService.createTaskQuery();
        List<Task> list = taskQuery.taskAssignee("吓抖抖").list();
        System.out.println(list);
    }

    /**
     * 完成一个用户任务
     */
    //@Override
    public void completeUserTask() {
        taskService.complete("70002");
    }

    /**
     * 查看流程部署并导出
     */
    //@Override
    public void queryProcessDeployment1() throws Exception {
        DeploymentQuery query = repositoryService.createDeploymentQuery();
        List<Deployment> list = query.deploymentName("请假流程").list();
        System.out.println(list);

        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> list1 = processDefinitionQuery.deploymentId(list.get(0).getId()).list();
        System.out.println(list1);

        ProcessDefinition df = list1.get(0);
        String saveResourceDir = "C:\\Users\\26825\\Documents\\";
        InputStream is = repositoryService.getResourceAsStream(df.getDeploymentId(), df.getResourceName());
        InputStream dis = repositoryService.getResourceAsStream(df.getDeploymentId(), df.getDiagramResourceName());
        OutputStream os = new FileOutputStream(saveResourceDir + df.getResourceName());
        FileOutputStream dos = new FileOutputStream(saveResourceDir + df.getDiagramResourceName());
        IOUtils.copy(is,os);
        IOUtils.copy(dis,dos);

        os.close();
        dos.close();
        is.close();
        dis.close();

    }

    /**
     * 删除一个流程部署
     */
    //@Override
    public void deleteProcDeployment(){
        //找出部署的流程
        Deployment deployment = repositoryService.createDeploymentQuery().deploymentName("请假流程").singleResult();

        //删除流程定义，流程部署，以及二进制的资源记录
        repositoryService.deleteDeployment(deployment.getId());
    }

    /**
     * 强制删除一个流程部署
     */
    //@Override
    public void deleteProcDeploymentPlus(){
        //找出部署的流程
        Deployment deployment = repositoryService.createDeploymentQuery().deploymentName("请假流程").singleResult();

        //删除流程定义，流程部署，以及二进制的资源记录
        repositoryService.deleteDeployment(deployment.getId(),true);
    }

    /**
     * 启动流程实例:
     *      前提是先已经完成流程定义的部署工作
     *
     *      背后影响的表：
     *      act_hi_actinst          已完成的活动信息
     *      act_hi_identitylink     参与者信息
     *      act_hi_procinst         流程实例
     *      act_hi_taskinst         任务实例
     *      act_ru_execution        执行表
     *      act_ru_identitylink     参与者信息
     *      act_ru_task             任务表
     */
    //@Override
    public void startPorcInstanceBusinessKey() {
        //创建流程实例,通过流程定义的id
        //通过流程部署的key启动
//        runtimeService.startProcessInstanceByKey("myProcess_1");
        //通过流程部署id启动
        runtimeService.startProcessInstanceById("holiday:1:47504","123456");
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().processDefinitionId("holiday:1:47504").list();
        System.out.println(list.get(0).getBusinessKey());
    }

    /**
     * 挂起或激活一个流程定义下所有的流程实例
     */
    //@Override
    public void suspendProcess1() {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> list = processDefinitionQuery.processDefinitionId("holiday:1:47504").list();
        ProcessDefinition processDefinition = list.get(0);
        boolean suspended = processDefinition.isSuspended();

        String processDefinitionId = processDefinition.getId();
        if (suspended) {
            repositoryService.activateProcessDefinitionById(processDefinitionId,true, null);
            System.out.println("流程定义ID为：" + processDefinitionId + "已激活");
        }else {
            repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
            System.out.println("流程定义ID为：" + processDefinitionId + "已挂起");
        }
    }

    /**
     * 挂起或激活一个特定的流程实例
     */
    //@Override
    public void suspendProcess2() {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processDefinitionId("holiday:1:47504").singleResult();
        boolean suspended = processInstance.isSuspended();
        String processInstanceId = processInstance.getProcessInstanceId();
        if (suspended){
            runtimeService.activateProcessInstanceById(processInstanceId);
            System.out.println("流程实例ID为：" + processInstanceId + "已激活");
        }else {
            runtimeService.suspendProcessInstanceById(processInstanceId);
            System.out.println("流程实例ID为：" + processInstanceId + "已挂起");
        }
    }

    /**
     * 启动流程，并制定执行人
     */
    //@Override
    public void startPorcInstance2() {
        // 指定流程执行人
        Map<String,Object> map = new HashMap<>();
        map.put("zhuguan","zhangsan");
        map.put("zongjingli","lisi");
        map.put("renshibu","wangwu");

        //通过流程部署id启动
        runtimeService.startProcessInstanceById("holiday:1:47504",map);
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().processDefinitionId("holiday:1:47504").list();
        System.out.println(list.get(0).getBusinessKey());
    }

    /**
     * 启动一个流程实例，并同时设置全局变量
     * @param tianshu 请假天数
     */
    //@Override
    public void startProcessInstance(int tianshu){
        //查询流程定义
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId("holiday:1:47504").singleResult();

        //定义全局变量
        Map<String,Object> variables = new HashMap<>();
        variables.put("tianshu",tianshu);
        variables.put("qingjiaren","路飞");
        variables.put("zhuguan","娜美");
        variables.put("zongjingli","山治");
        variables.put("renshibu","乔巴");

        //启动流程，并设置全局流程变量
        runtimeService.startProcessInstanceById(processDefinition.getId(),variables);
    }

    /**
     * 在流程运行时设置全局变量
     * @param variables 全局流程变量
     * @param processInstanceId 流程实例id
     */
    //@Override
    public void setGlobleVariables(Map<String,Object> variables,String processInstanceId) {
        runtimeService.setVariables(processInstanceId,variables);
    }

    /**
     * 用户完成任务的时候指定全局变量
     * @param variables 全局流程变量
     * @param taskId 用户任务id
     */
    //@Override
    public void setVariablesWhenComplateUserTast(Map<String,Object> variables,String taskId) {
        taskService.complete(taskId,variables);
    }

    /**
     * 用户任务上指定变量
     * @param variables
     * @param taskId
     */
    //@Override
    public void setVariablesOnUserTask(Map<String,Object> variables,String taskId) {
        taskService.setVariables(taskId,variables);
    }

    /**
     * 在用户的任务流程节点上设置局部变量
     * 局部变量的作用域为当前的流程节点
     * @param variables 局部变量
     * @param taskId 任务id
     */
    //@Override
    public void setLocalVariablesOnUserTask(Map<String,Object> variables,String taskId) {
        taskService.setVariablesLocal(taskId,variables);
    }

    /**
     * 在用户完成任务流程时设置局部变量
     * 局部变量的作用域为当前的流程节点
     * @param variables 局部变量
     * @param taskId 任务id
     */
    //@Override
    public void complateAndSetLocalVariablesOnUserTask(Map<String,Object> variables,String taskId) {
        //第三个参数表示，变量为局部变量
        taskService.complete(taskId,variables,true);
    }
}
